import 'dart:async';

import 'package:collection/src/list_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_tiktok/controller/tikTokVideoListController.dart';
import 'package:flutter_tiktok/style/physics.dart';
import 'package:flutter_tiktok/views/tikTokVideo.dart';
import 'package:get/get.dart';
import 'package:jet_rails/jr_app/jr_models/jr_video_model.dart';
import 'package:jet_rails/jr_app/jr_views/jr_main/jr_main_controller.dart';
import 'package:jet_rails/jr_app/jr_views/jr_video/jr_video_controller.dart';
import 'package:jet_rails/jr_services/jr_services.dart';
import 'package:jet_rails/jr_utils/jr_logger.dart';
import 'package:jet_rails/jr_utils/jr_snippet.dart';
import 'package:video_player/video_player.dart';

class JrVideoFeed extends StatefulWidget {
  final List<JrVideoModel> videoModelList;

  const JrVideoFeed({super.key, required this.videoModelList});
  @override
  _JrVideoFeedState createState() => _JrVideoFeedState();
}

class _JrVideoFeedState extends State<JrVideoFeed> with WidgetsBindingObserver {
  static const String TAG = 'JrVideoFeed';
  PageController? _pageController;
  TextEditingController? _textEditingController;
  FocusNode? _focusNode;
  TikTokVideoListController? _videoListController;

  List<Widget> danmuList = [];
  bool _isScrollable = true;
  Timer? _throttleTimer;
  bool get inVideoTab {
    try {
      return Get.find<JrMainController>().currentIndex.value == 1;
    } catch (e) {
      return false;
    }
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) async {
    if (state != AppLifecycleState.resumed) {
      _videoListController?.currentPlayer?.pause();
    }
  }

  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    JrLogger.d('------jvf initState $hashCode');
    refreshVideoList();
    super.initState();
  }

  refreshVideoList() {
    try {
      disposeAll();
      _pageController = PageController();
      _textEditingController = TextEditingController();
      _focusNode = FocusNode();
      _videoListController = TikTokVideoListController();
      JrLogger.d(
          'refreshVideoList state:$hashCode page:${_pageController?.hashCode} text:${_textEditingController?.hashCode} focus:${_focusNode?.hashCode} video:${_videoListController?.hashCode}',
          tag: TAG);
      Get.find<JrVideoController>().ttVideoListController = _videoListController;
      _videoListController?.init(
          pageController: _pageController!,
          initialList: widget.videoModelList
              .mapIndexed(
                (index, e) => VPVideoController(
                  videoInfo: e,
                  builder: () => VideoPlayerController.networkUrl(Uri.parse(e.mediaUrl ?? '')),
                ),
              )
              .toList(),
          videoProvider: (int index, List<VPVideoController> list) async {
            return [];
          },
          afterLoadIndex: (player) => inVideoTab);
      _videoListController?.addListener(() {
        if (mounted) {
          setState(() {});
        }
      });
      if (mounted) {
        setState(() {});
      }
      Future.delayed(const Duration(milliseconds: 1500), () {
        if (inVideoTab && mounted && _videoListController?.index.value == 0) {
          _videoListController?.playerOfIndex(0)?.play();
        }
      });
    } catch (e) {
      JrLogger.e('refreshVideoList error: $e', tag: TAG);
    }
  }

  @override
  void dispose() {
    try {
      JrLogger.d(
          'before dispose state:$hashCode page:${_pageController?.hashCode} text:${_textEditingController?.hashCode} focus:${_focusNode?.hashCode} video:${_videoListController?.hashCode}',
          tag: TAG);
      WidgetsBinding.instance.removeObserver(this);
      disposeAll();
    } catch (e) {
      JrLogger.e('dispose error: $e', tag: TAG);
    }
    super.dispose();
    JrLogger.d(
        'after dispose state:$hashCode page:${_pageController?.hashCode} text:${_textEditingController?.hashCode} focus:${_focusNode?.hashCode} video:${_videoListController?.hashCode}',
        tag: TAG);
  }

  disposeAll() {
    _pageController?.dispose();
    _pageController = null;
    _textEditingController?.dispose();
    _textEditingController = null;
    _focusNode?.dispose();
    _focusNode = null;
    _videoListController?.currentPlayer?.pause().then((value) {
      _videoListController?.dispose();
      _videoListController = null;
    });
    danmuList.clear();
    _throttleTimer?.cancel();
    _throttleTimer = null;
    _isScrollable = true;
  }

  @override
  Widget build(BuildContext context) {
    double a = MediaQuery.of(context).size.aspectRatio;
    bool hasBottomPadding = a < 0.55;

    return _videoListController == null
        ? Container()
        : PageView.builder(
            physics: _isScrollable ? const QuickerScrollPhysics() : const NeverScrollableScrollPhysics(),
            controller: _pageController,
            scrollDirection: Axis.vertical,
            itemCount: _videoListController!.videoCount,
            onPageChanged: _onPageChange,
            itemBuilder: (context, i) {
              var player = _videoListController!.playerOfIndex(i)!;
              var data = player.videoInfo!;
              var videoModel = widget.videoModelList[i];
              Widget currentVideo = Center(
                child: AspectRatio(
                  aspectRatio: player.controller.value.aspectRatio,
                  child: VideoPlayer(player.controller),
                ),
              );

              currentVideo = TikTokVideoPage(
                hidePauseIcon: !player.showPauseIcon.value,
                aspectRatio: 9 / 16.0,
                key: Key(data.url + '$i'),
                tag: data.url,
                bottomPadding: hasBottomPadding ? 16.0 : 16.0,
                onSingleTap: () async {
                  if (_focusNode?.hasFocus == true) {
                    _focusNode?.unfocus();
                    _textEditingController?.clear();
                    return;
                  }
                  if (player.controller.value.isPlaying) {
                    await player.pause();
                  } else {
                    await player.play();
                  }
                  setState(() {});
                },
                onAddFavorite: () {
                  if (!videoModel.like) {
                    Get.find<JrVideoController>().toggleLikeStatus(videoModel);
                  }
                  setState(() {});
                },
                video: currentVideo,
              );
              return Stack(
                children: <Widget>[
                  currentVideo,
                  Positioned(
                      top: 100.h,
                      left: 20.w,
                      height: 40.h,
                      width: 355.w,
                      child: Row(
                        children: [
                          CircleAvatar(
                            radius: 20,
                            backgroundImage: videoModel.author?.getAvatarUrl != null
                                ? NetworkImage(videoModel.author!.getAvatarUrl)
                                : null,
                          ),
                          SizedBox(width: 16.w),
                          Expanded(
                            child: Text(videoModel.author?.nickname ?? '',
                                overflow: TextOverflow.ellipsis,
                                style: TextStyle(color: Colors.white, fontSize: 14.sp)),
                          ),
                        ],
                      )),
                  Positioned(
                      top: 150.h,
                      left: 20.w,
                      width: 355.w,
                      child: Text(videoModel.title ?? '',
                          maxLines: 3,
                          overflow: TextOverflow.ellipsis,
                          style: TextStyle(color: Colors.white, fontSize: 16.sp))),
                  Positioned(
                    bottom: 100.h,
                    right: 20.w,
                    height: 35.h,
                    width: 35.w,
                    child: GestureDetector(
                      onTap: () {
                        _focusNode?.requestFocus();
                      },
                      child: Image.asset(
                        'assets/webp/icon_danmaku.webp',
                        width: 28,
                        height: 28,
                      ),
                    ),
                  ),
                  Positioned(
                    bottom: 150.h,
                    right: 20.w,
                    height: 35.h,
                    width: 35.w,
                    child: StatefulBuilder(
                      builder: (context, setState) => GestureDetector(
                        onTap: () {
                          Get.find<JrVideoController>().toggleLikeStatus(videoModel);
                          setState(() {});
                        },
                        child: Image.asset(
                          videoModel.like ? 'assets/webp/icon_like_active.webp' : 'assets/webp/icon_like_default.webp',
                          width: 28,
                          height: 28,
                        ),
                      ),
                    ),
                  ),
                  Positioned(
                    bottom: 200.h,
                    right: 20.w,
                    height: 35.h,
                    width: 35.w,
                    child: GestureDetector(
                      onTap: () {
                        if (videoModel.author?.userId != null) {
                          JrSnippets.popMoreMenuDialog(videoModel.author!.userId);
                        }
                      },
                      child: Image.asset(
                        'assets/webp/icon_more_option.webp',
                        width: 28,
                        height: 28,
                      ),
                    ),
                  ),
                  Positioned(
                      bottom: 0,
                      height: 60.h,
                      child: Container(
                        height: 60.h,
                        width: 375.w,
                        decoration: const BoxDecoration(
                            gradient: LinearGradient(
                                colors: [Color(0xFF2B1628), Color(0xFF4E3B7D)],
                                begin: Alignment.centerLeft,
                                end: Alignment.centerRight)),
                        child: Row(
                          children: [
                            SizedBox(width: 20.w),
                            Expanded(
                              child: TextField(
                                controller: _textEditingController,
                                focusNode: _focusNode,
                                onSubmitted: (value) {
                                  postDanmaku(value);
                                  _textEditingController?.clear();
                                },
                                decoration: const InputDecoration(
                                  border: InputBorder.none,
                                ),
                                style: const TextStyle(color: Colors.white),
                              ),
                            ),
                            SizedBox(width: 20.w),
                          ],
                        ),
                      )),
                  ...danmuList
                ],
              );
            },
          );
  }

  _onPageChange(index) {
    /// throttle PageView scroll event
    setState(() {
      _isScrollable = false;
      danmuList = [];
    });

    _throttleTimer?.cancel();

    _throttleTimer = Timer(Duration(milliseconds: 500), () {
      setState(() {
        _isScrollable = true;
      });
    });
  }

  postDanmaku(String content) {
    danmuList.add(FloatingBubble(
        content: Container(
      width: 300,
      child: Row(
        children: [
          CircleAvatar(
            radius: 16.r,
            backgroundImage: NetworkImage(JrServices.instance.loginUser.value.getAvatarUrl),
          ),
          SizedBox(width: 8.w),
          Text(content,
              maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(color: Colors.white, fontSize: 14.sp))
        ],
      ),
    )));
    setState(() {});
  }
}

class FloatingBubble extends StatefulWidget {
  final Widget content;

  const FloatingBubble({Key? key, required this.content}) : super(key: key);

  @override
  _FloatingBubbleState createState() => _FloatingBubbleState();
}

class _FloatingBubbleState extends State<FloatingBubble> with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _fadeAnimation;
  late Animation<double> _positionAnimation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(seconds: 5),
      vsync: this,
    );

    _fadeAnimation = Tween<double>(begin: 1.0, end: 0.0).animate(_controller);
    _positionAnimation = Tween<double>(begin: 100.0, end: 250.0).animate(_controller);

    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) {
        return Positioned(
          bottom: _positionAnimation.value,
          left: 20.w,
          child: Opacity(
            opacity: _fadeAnimation.value,
            child: widget.content,
          ),
        );
      },
    );
  }
}
